GO
1. 正则表达式入门
1.1. 定义
正则表达式是处理字符串的方法,它是以行为单位来进行字符串的处理行为,通过一些特殊符号的辅助,可以轻易达到查找、删除、替换某特定字符的目的。它是一种规则,只要某工具支持正则表达式,便可以使用这种规则。(支持正则的工具有:vi、grep、awk、sed等)
注意:
- 使用正则表达式时,需要注意当时环境的语系是什么,否则结果会有所不同。
- 正则表达式的特殊字符与一般在命令行输入命令的通配符并不相同。
1.2. 特殊符号
特殊符号 | 代表意义 |
---|---|
[:alnum:] | 英文大小写字符及数字,即0-9,A-Z,a-z |
[:alpha:] | 英文大小写字符,即A-Z,a-z |
[:lower:] | 小写字母,即a-z |
[:upper:] | 大写字母,即A-Z |
[:digit:] | 数字,即0-9 |
[:blank:] | 空格键与[Tab]按键 |
[:cntrl:] | 键盘上面的控制按键,即包括CR,LF,Tab,Del等 |
[:graph:] | 除了空格符(空格键与[Tab]按键)外的其它所有按键 |
[:print:] | 任何可以被打印出来的字符 |
[:punct:] | 标点符号(punctuation symbol),即” ‘ ? ! ; : # $ |
[:space:] | 任何会产生空白的字符,包括空格键[Tab]CR等 |
[:xdigit:] | 十六进制的数字类型,包括0-9,A-F,a-f的数字与字符 |
上表最常用的是前五个,要熟记!
1.3. 基础正则表达式
RE字符 | 意义 |
---|---|
^word | 待查找的字符串(word)在行首 |
word$ | 待查找的字符串(word)在行尾 |
. 点 | 代表一定有一个任意字符的字符 |
\ | 转义字符,将特殊符号的特殊意义去除 |
*星号 | 重复零个到无穷多个的前一个字符 |
.* | 表示任意个字符(包含空行) |
[list] | 从字符集合的RE字符里找出想要选取的字符 |
[n1-n2] | 从字符集合的RE字符里面找出想要选取的字符范围 |
[^list] | 从字符集合的RE字符里面找出不要的字符串或范围 |
{n,m} | 连续n到m的前一个RE字符,若为{n}则是连续n个前一个RE字符,若为{n,}则是连续n个以上的前一个RE字符 |
1.4. 扩展正则表达式
RE字符 | 意义 |
---|---|
+ | 重复一个或一个以上的前一个RE字符 |
? | 零个或一个的前一个RE字符 |
“竖杠” | 用或(or)的方式找出数个字符串 |
() | 找出 “组”字符串 |
()+ | 多个重复组的判别 |
1.5. 注意
- {}、+、-、|等在grep中使用时需要加反斜杠脱义,而在egrep直接使用即可。
- egrep 和 grep -E 的效果是一样的。
- sed -r 是使用扩展正则表达式的参数。
2. 支持正则的常用工具
2.1. grep 和 egrep
2.1.1. grep
grep是以行为单位,在数据中进行字符串对比,并打印出所匹配到的字符串及其整行内容。
常用参数 | 参数说明 |
---|---|
-A | 后面可加数字,为after之意,列出匹配到的行及后面的n行 |
-B | 后面可加数字,为before之意,列出匹配到的行及前面的n行 |
-C | 综合-A和-B的功能 |
-n | 显示出所匹配到的行的行号 |
-v | 反向匹配 |
-i | 忽略字母的大小写 |
-c | 打印符合要求的行的个数 |
-o | 打印符合要求的关键字出现的字数 |
-r | 会把目录下面所有的文件全部遍历(该目录下的子目录下的文件也会遍历) |
–color=auto | 自动加上颜色显示出关键字 |
2.1.2. egrep
grep
和 grep -E
是别名的关系,是grep使用扩展正则表达式要用的参数。grep默认只支持基础正则表达式,所以,当使用到扩展正则表达式的时候,就要用这个命令.
2.1.3. 一些例子
- 过滤出带有某个关键词的行并输出行号
grep -n 'root' 1.txt
- 过滤出不带有某个关键字的行并输出行号
grep -n -v 'root; 1.txt
- 过滤出所有包含数字的行
grep '[0-9]' 1.txt
- 过滤出所有不包含数字的行
grep -v '[0-9]' 1.txt
- 去除所有以‘#’开头的行
grep -v '^#' 1.txt
- 去除所有空行和以‘#’开头的行
grep -v '^$' 1.txt | grep -v '^#'
- 过滤出以英文字母开头的行
grep '^[a-zA-Z]' 1.txt
- 过滤出以非数字开头的行
grep '^[^0-9]' 1.txt
- 过滤任意一个或多个字符
grep 'r.o' 1.txt
;grep 'r*t' 1.txt
;grep 'r.*p' 1.txt
- . 表示任意一个字符
- * 表示零个或多个*前面的字符
- .* 表示零个或多个任意字符,空行也包含在内
grep -E 'ro?t' 1.txt
?表示匹配零个或一个?前面的字符grep -E 'ro+t' 1.txt
+表示匹配一个或多个+前面的字符- 指定过滤字符次数
grep 'o\{2\}' 1.txt
egrep 'o+' 1.txt
表示1个或多个前面的字符egrep 'o?' 1.txt
表示0个或1个前面的字符egrep 'roo|body' 1.txt
匹配roo或者匹配body(grep ‘roo\|body’ 1.txt 也可以实现这个功能,即用转义符把|转义)egrep 'r(oo)|(at)o' 1.txt
用括号表示一个整体egrep '(oo)+' 1.txt
表示匹配1个或多个‘oo’egrep '(oo){2}' 1.txt
表示匹配有两次’oo’egrep '(oo){1,2}' 1.txt
表示匹配有一次或两次’oo’
2.2. sed
2.2.1. sed 的用法
sed是一个很好的文件处理工具,本事是一个管道命令,主要是以行为单位进行处理,可以将数据进行替换、删除、新增、选取等特定工作。sed的用法如下:
sed的命令行格式为 sed [-nefri] 'command' 输入文本
2.2.2. sed 常用选项
选项 | 意义 |
---|---|
-n | 使用安静(silent)模式。在一般的sed的用法中,所有来自stdin的数据都会被列到屏幕上。但如果加上-n选项后,则只有经过sed特殊处理的那一行(或者动作)才会被列出来。 |
-e | 直接在命令行模式上进行sed的动作编辑 |
-f | 直接将sed的动作写在一个文件内,-f filename 则可以执行filename内的sed动作 |
-r | sed在使用扩展正则表达式需要加的参数(默认是基础正则表达式的使用) |
-i | 直接修改读取的文件内容,而不是仅仅显示在屏幕上 |
2.2.3. sed 常用命令
命令 | 意义 |
---|---|
a | 新增,a的后面可以接字符串,而这些字符串会在新的一行出现(当前的下一行) |
c | 取代,c的后面可以接字符串,而这些字符串可以取代n1,n2之间的行 |
d | 删除,因为是删除操作,所以d后面通常不接任何东西 |
i | 插入,i的后面可以接字符串,而这些字符串会在新的一行出现(当前的上一行) |
p | 打印,即将某个选择的数据打印出来。通常p会与参数 sed -n 一起使用 |
s | 替换,可以直接进行替换的工作。通常这个s的动作可以搭配正则表达式。例如 1,20s/old/new/g |
2.2.4. sed 一些常用例子
1. 打印指定行
- 打印第10行:
sed -n '10p' 1.txt
- 打印1到4行:
sed -n '1,4p' 1.txt
- 打印5行到最后:
sed -n '5,$p' 1.txt
2. 打印包含某个字符串的行
- 打印出包含root的行:
sed -n '/root/p' 1.txt
- 可以使用正则表达式中的符号,例如^、.、*、$等,-r选项是使用扩展正则表达式时要加的选项(默认是基础正则表达式的使用)
3. -e 可以实现同时进行多个任务的选项
sed -e '/root/p' -e '/body/p' -n 1.txt
匹配root和body的行,如果一行中有root和body,则该行会被打印两次- 也可以用分号;实现:
sed '/root/p ; /body/p' -n 1.txt
功能同上
4. 删除行
- 删除包含root的行:
sed '/root/d' 1.txt
- 删除第一行,其它行显示:
sed '1d' 1.txt
- 删除1到10行,其它行显示:
sed '1,10d' 1.txt
5. 替换
sed '1,2s/ot/to/g' 1.txt
其中的s就是替换的意思,g为全局替换,否则只替换本行中出现的第一个,/分隔符也可以用#、@等符号- 删除所有数字:
sed 's/[0-9]//g' 1.txt
- 删除所有非数字:
sed 's/[^0-9]//g' 1.txt
- 调换两个字符串的位置:
head -n2 1.txt | sed 's/\(root\)\(.*\)\(bash\)/\3\2\1/'
或head -n2 1.txt | sed -r 's/(root)(.*)(bash)/\3\2\1/'
- 直接修改文件内容:
sed -i 's/ot/to/g' 1.txt
2.2.5. sed 练习题和答案
- 把/etc/passwd 复制到 /root/test.txt,用sed打印所有行:
/bin/cp /etc/passwd /root/test.txt ; sed -n '1,$p' test.txt
- 打印test.txt的3到10行:
sed -n '3,10p' test.txt
- 打印test.txt中包含root的行:
sed -n '/root/p' test.txt
- 删除test.txt的15行以及以后所有行:
sed '15,$d' test.txt
- 删除test.txt中包含bash的行:
sed '/bash/d' test.txt
- 替换test.txt 中’root’为’toor’:
sed 's/root/toor/g' test.txt
- 替换text.txt中/sbin/nologin为/bin/login:
sed 's#sbin/login#bin/login#g' test.txt
- 删除test.txt中5到10行所有的数字:
sed '5,10s/[0-9]//g' test.txt
- 删除test.txt中所有的特殊字符(除了数字以及大小写字母):
sed 's/[^0-9a-zA-Z]//g' test.txt
- 把test.txt中第一个单词和最后一个单词调换位置:
sed -r 's/(^[a-zA-Z]+)([^a-zA-Z].*[^a-zA-Z])([a-zA-Z]+$)/\3\2\1/' test.txt
- 把test.txt中出现的第一个数字和最后一个单词调换位置:
sed -r 's/(^[^0-9]*)([0-9]+)([^0-9].*[^a-zA-Z]+$)/\1\4\3\2/' test.txt
- 把test.txt中第一个数字移动到行末尾:
sed -r 's/(^[^0-9]*)(^[0-9]+)([^0-9].*$)/\1\3\2/' test.txt
- 在test.txt中20行到末行最前面加”aaa:”:
sed '20,$s/^.*$/aaa:&/' test.txt
2.2.6. sed 学习说明
sed的常用功能基本上都在上面,这些就足够日常运维工作的使用了,若是遇到复杂的需求,再去查一下资料即可。
2.3. awk
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说,awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk有3个不同版本:awk、nawk和gawk,未作特别说明,一般指gawk,gawk是awk的GNU版本。
awk其名称得自于它的创始人 Alfred Aho、Peter Weinberger和Brian Kernighan 姓氏的首个字母。实际上AWK的确拥有自己的语言:AWK程序设计语言,三位创建组已将它正式定义为”样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
2.3.1. awk 初学笔记
1. awk的用法
awk和sed一样,都是流式编辑器,针对文档中的行来操作,一行一行地执行。awk兼具sed的所有功能,而且更加强大。awk工具其实是很复杂的(有专门的书来介绍它的应用),对于初学者来说,只要能处理日常管理工作中的问题即可。鉴于此,下面的内容仅仅介绍了比较常见的awk应用。
- 截取文档中的某个段
- 截取文档中的某个段
awk -F':' '{print $1}' 1.txt
- 本例中,-F选项的作用是指定分隔符。若不加-F选项,则以空格或者tab为分隔符。print为打印的动作,用来打印某个字段。$1为第一个字段,$2为第2个字段,以此类推。但是$0比较特殊,它表示整行。
awk -F':' '{print $0}' 1.txt
- 注意awk的格式,-F后面紧跟单引号,单引号里面为分隔符。print的动作要用{}括起来,否则会报错。
- 本例中,-F选项的作用是指定分隔符。若不加-F选项,则以空格或者tab为分隔符。print为打印的动作,用来打印某个字段。$1为第一个字段,$2为第2个字段,以此类推。但是$0比较特殊,它表示整行。
- print也可以打印自定义的内容,但是自定义的内容要用双引号括起来
awk -F':' '{print $1"#"$2"#"$3"#"$4}' 1.txt
- 匹配字符或者字符串
- 匹配字符或字符串
awk '/oo/' 1.txt
- 这种用法跟sed的用法类似,能实现grep的功能,但没有颜色显示,也不如grep用起来方便。
- 可针对某个段匹配
awk -F':' '$1~/oo/' 1.txt
- 这里的~就是匹配的意思。
- 多次匹配
awk -F':' '/root/ {print $1,$3}; $1~/test/; $3~/20/' 1.txt
- 条件操作符
awk中可以用逻辑符号进行判断,比如==就是等于,也可以理解为精确匹配。另外还有>、>=、<、<=、!=等。值得注意的是,在和数字比较时,若把比较的数字用双引号括起来,那么awk不会认为是数字,而会认为是字符,不加双引号会认为是数字。
- 条件操作符 ==,>,<,!=,>=,<=
awk -F':' '$3=="0"' 1.txt
awk -F':' '$3>="500"' 1.txt
awk -F':' '$7!="/sbin/mologin"' 1.txt
awk -F':' '$3<$4' 1.txt
awk -F':' '$3>"5" && $3<"7"' 1.txt
另外还可以使用&&和||,它们分别表示”并且”和”或者”。
awk -F':' '$3>"5" && $7=="/bin/bash"' 1.txt
awk -F':' '$3>"5" || $7=="/bin/bash"' 1.txt
- awk的内置变量
awk的常用内置变量有OFS、NF和NR。OFS和-F选项有类似的功能,也是用来定义分隔符的,但是它是在输出的时候定义;NF表示用分隔符分隔后一共有多少段,NR表示行号。
- OFS的用法:
awk -F':' '{OFS="#"} {print $1,$3,$4}' 1.txt
awk -F':' '{OFS='#'} {if ($3>1000) {print $1,$2,$3,$4}}' 1.txt
- NF的具体用法:
head -n3 1.txt | awk -F ':' '{print NF}'
head -n3 1.txt | awk -F ':' '{print $NF}'
- 这里NF是多少段,$NF是最后 一段的值。
- NR的用法:
head -n3 1.txt | awk -F ':' '{print NR}'
- 还可以用NR作为判断条件,比如打印20行以后的行
awk 'NR>20' 1.txt
- NR也可以和段匹配一起使用,如
awk -F ':' 'NR>20 && $1 ~/ssh/' 1.txt
- awk中的数学运算
- awk可以更改段值
awk -F ':' '$1="root"' 1.txt
- 也可以对各个段的值进行数学运算,例如把第三段和第四段的值相加并赋予第七段
awk -F ':' '{$7=$3+$4;print $0}' 1.txt
- 计算第三段的总和
awk -F ':' ‘{(tot=toy+$3)};END {print tot}’ 1.txt
- awk中也可以使用if 关键词
awk -F ':' '{if ($1=="root") print $0}' 1.txt
~~~
说明:以上介绍的内容仅仅是最基本的内容,这些东西完全可以满足日常工作的需求。若是遇到比较复杂的需求,再去查阅资料学习更深的东西。
2. awk练习题
题目:
- 用awk打印整个test.txt。(以下操作都是针对test.txt的,用awk工具实现)
- 查找所有包含bash的行。
- 用:作为分隔符,查找第3个字段等于o的行。
- 用:作为分隔符,查找第1个字段为root的行,并把该段的root换成toor。(可以连同sed一起使用)
- 用:作为分隔符,打印最后一个字段。
- 打印行数大于20的所有行。
- 用:作为分隔符,打印所有第3个字段小于第4个字段的行。
- 用:作为分隔符,打印第1个字段以及最后一个字段,并且中间用@连接(例如,第1行应该是这样的形式:root@/bin/bash)
- 用:作为分隔符,把整个文档的第4个字段相加,求和。
答案:
awk '{print $0}' test.txt
awk '/bash/' test.txt
awk -F':' '$3=="o"' test.txt
awk -F':' '$1=="root"' test.txt | sed 's/root/toor/'
awk -F':' '{print $NF}' test.txt
awk -F':' 'NR>20' test.txt
awk -F':' '$3<$4' test.txt
awk -F':' '{print $1"@"$NF}' test.txt
awk -F':' '{(sum+=$4)}; END {print sum}' test.txt
2.3.2. awk 入门笔记
1. 使用方法
使用格式为 : awk '{pattern + action}' {filename}
尽管操作可能会很复杂,但语法总是这样,其中pattern表示awk在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令。花括号({ })不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。pattern就是要表示的正则表达式,用斜杠括起来。
awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其它文本操作。完整的awk脚本通常用来格式化文本文件中的信息。
通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。
2. 调用awk的三种方式
- 命令行方式
格式:awk [-F field-separator] 'conmmands' input-file(s)
其中,commands是真正awk命令,[-F域分隔符]是可选的。input-file(s)是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指定-F域分隔符的情况下,默认的域分隔符是空格。
- shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk
- 将所有的awk命令插入一个单独文件,然后调用
格式 awk -f awk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。
在这里,主要用的是第一种方式:命令行方式。
3. 入门实例
假设last -n 5
的输出如下:
示例1
如果只是显示最近登陆的5个账号
awk工作流程是这样的:读入有’\n’换行符分割的一条记录,然后将记录按照指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分割符是”空白键”或”[tab]键”,所以$1表示登陆用户,$3表示登陆用户ip,以此类推。
示例2
如果只是显示/etc/passwd的账户
这种是awk+action的示例,每行都会执行action{print $1}。-F指定域分隔符为’:’。
示例3
如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割
示例4
如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列明name,shell,在最后一行添加blue,/bin/nosh
awk的工作流程是这样的:先执行BEGiNG,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分割符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录……知道所有的记录都读完,最后执行END操作。
示例5
搜索/etc/passwd有root关键字的所有行
这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。
搜索支持正则,例如找root开头的:awk -F: '/^root/' /etc/passwd
示例6
搜索/etc/passwd有root关键字的所有行,并显示对应的shell
这里指定了action{print $7}
4. awk 内置变量
awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。
变量名 | 值的意义 |
---|---|
ARGC | 命令行参数个数 |
ARGV | 命令行参数排列 |
ENVIRON | 支持队列中系统环境变量的使用 |
FILENAME | awk浏览的文件名 |
FNR | 浏览文件的记录数 |
FS | 设置输入域分隔符,等价于命令行 -F 选项 |
NF | 浏览记录的域的个数 |
NR | 已读的记录数 |
OFS | 输出域分隔符 |
ORS | 输出记录分隔符 |
RS | 控制记录分隔符 |
$0 | 整条记录 |
$1 | 当前行的第一个域 |
$n | 当前行的第n个域 |
示例如下:
统计/etc/passwd的文件名,每行的行号,每行的列数,对应的完整行内容:
使用printf替代print,可以让代码更加简洁、易读:
5. print 和 printf
awk中同时提供了print和printf两种打印输出的函数。
其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。
printf函数,其用法和C语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。
6. awk编程
变量和赋值
除了awk的内置变量,awk还可以自定义变量。
下面统计/etc/passwd的账户人数
count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开。
上面的用法里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0:
统计某个目录下的文件占用的字节数
如果以M为单位显示:
注意,统计不包括目录的子目录。
条件语句
awk中的条件语句是从C语言中借鉴而来的,见如下声明方式:
统计某个目录下的文件占用的字节数,过滤4096大小的文件(一般都是目录)
循环语句
awk中的循环语句同样借鉴于C语言,支持while、do-while、for、break、continue,这些关键字的语义和C语言中的语义完全相同。
数组
因为awk中数组的下表可以是数字和字母,数字的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。
显示/etc/passwd的账户
这里使用for循环遍历数组。
2.3.3. awk 学习说明
以上便是awk最常用的使用方法。但如果想深学awk编程,请参考专业书籍。
OK